#include "stdafx.h"
#include "ImageRender.h"
#include "olectl.h" // for OleLoadPicture()

#define HIMETRIC_INCH   2540    // HIMETRIC units per inch

bool ImageRender::GetImageSize(CDC*       pDC,
							   LPCTSTR    szFile,
							   int*       pnHeight,
							   int*       pnWidth)
{
    LPPICTURE gpPicture = NULL;

    if (!LoadPictureFile(szFile, &gpPicture))
        return FALSE;

    //Get width and height of picture
    long hmWidth  = 0;
    long hmHeight = 0;

    gpPicture->get_Width (&hmWidth);
    gpPicture->get_Height(&hmHeight);

    int nPixX = pDC->GetDeviceCaps(LOGPIXELSX);
    int nPixY = pDC->GetDeviceCaps(LOGPIXELSY);

    //For printers, pixels per inch is really DPI, so be careful!
    if (pDC->IsPrinting())
    {
		nPixX = 96;
        nPixY = 96;
    }

    //Convert to device units
    *pnWidth  = MulDiv(hmWidth,  nPixX, HIMETRIC_INCH);
    *pnHeight = MulDiv(hmHeight, nPixY, HIMETRIC_INCH);

    return TRUE;
}

bool ImageRender::DrawImage(CDC* pDC, LPCTSTR szFile, CRect rectView, CRect rectImage)
{
	if (pDC == NULL || wcscmp(szFile, _T("")) == 0)
		return FALSE;

	LPPICTURE gpPicture = NULL;

	if (ImageRender::LoadPictureFile((LPCTSTR)szFile, &gpPicture))
	{
		//Get width and height of picture
		long hmWidth  = 0;
		long hmHeight = 0;

		gpPicture->get_Width (&hmWidth);
		gpPicture->get_Height(&hmHeight);

		//Use to get height and width for display

		CRect rectI = rectImage;
		rectI.NormalizeRect();

		int nWidth = rectI.Width();
		int nHeight= rectI.Height();

		HRESULT hrP = NULL;

		hrP = gpPicture->Render(pDC->m_hDC, 
								rectImage.left, 
								rectImage.top,
								nWidth,
								nHeight,
								0,
								hmHeight,
								hmWidth,
								-hmHeight,
								&rectView);
		gpPicture->Release();

		if (SUCCEEDED(hrP))
			return TRUE;
	}

	return FALSE;
}

bool ImageRender::LoadPictureFile(LPCTSTR szFile, LPPICTURE* pgpPicture)
{
	// open file
	HANDLE hFile = CreateFile(szFile,
							  GENERIC_READ,
							  0,
							  NULL,
							  OPEN_EXISTING,
							  0,
							  NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
		//AfxMessageBox ("Could not read file");
		return FALSE;
	}

	// get file size
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	if (dwFileSize == (DWORD)-1)
	{
		CloseHandle(hFile);
		//AfxMessageBox ("File seems to be empty");
		return FALSE;
	}

	// alloc memory based on file size
	LPVOID pvData = NULL;
	HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
	if (hGlobal == NULL)
	{
		CloseHandle(hFile);
		//AfxMessageBox ("Could not allocate memory for image");
		return FALSE;
	}

	pvData = GlobalLock(hGlobal);
	if (pvData == NULL)
	{
		GlobalUnlock(hGlobal);
		CloseHandle(hFile);
		//AfxMessageBox ("Could not lock memory for image");
		return FALSE;
	}

	DWORD dwBytesRead = 0;

	// read file and store in global memory
	BOOL bRead = ReadFile(hFile,
						  pvData,
						  dwFileSize,
						  &dwBytesRead,
						  NULL);

	GlobalUnlock(hGlobal);
	CloseHandle(hFile);

	if (!bRead)
	{
		//AfxMessageBox ("Could not read file");
		return FALSE;
	}

	LPSTREAM pstm = NULL;

	// create IStream* from global memory
	HRESULT hr = CreateStreamOnHGlobal(hGlobal,
									   TRUE,
									   &pstm);
	if (!(SUCCEEDED(hr)))
	{
		//AfxMessageBox ("CreateStreamOnHGlobal() failed");
		if (pstm != NULL)
			pstm->Release();

		return FALSE;
	}
	else if (pstm == NULL)
	{
		//AfxMessageBox ("CreateStreamOnHGlobal() failed");
		return FALSE;
	}

	// Create IPicture from image file
	if (*pgpPicture)
		(*pgpPicture)->Release();

	hr = ::OleLoadPicture(pstm, 
						  dwFileSize,
						  FALSE,
						  IID_IPicture,
						  (LPVOID *)&(*pgpPicture));
	if (!(SUCCEEDED(hr)))
	{
		pstm->Release();
		//AfxMessageBox("Could not load image (hr failure)");
		return FALSE;
	}
	else if (*pgpPicture == NULL)
	{
		pstm->Release();
		//AfxMessageBox("Could not load image (pgpPicture failure)");
		return FALSE;
	}

	pstm->Release();

	return TRUE;  //Made it ...!
}